//! 被动扫描引擎配置

use crate::alert::AlertConfig;
use crate::dedup::DedupConfig;
use crate::processor::ProcessorConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// 被动扫描引擎主配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScanConfig {
    /// 引擎基本配置
    pub engine: EngineConfig,
    /// 去重配置
    pub dedup: DedupConfig,
    /// 处理器配置
    pub processor: ProcessorConfig,
    /// 告警配置
    pub alert: AlertConfig,
    /// 存储配置
    pub storage: StorageConfig,
    /// 规则配置
    pub rules: RulesConfig,
    /// 指纹识别配置
    pub fingerprint: FingerprintConfig,
}

impl Default for ScanConfig {
    fn default() -> Self {
        Self {
            engine: EngineConfig::default(),
            dedup: DedupConfig::default(),
            processor: ProcessorConfig::default(),
            alert: AlertConfig::default(),
            storage: StorageConfig::default(),
            rules: RulesConfig::default(),
            fingerprint: FingerprintConfig::default(),
        }
    }
}

impl ScanConfig {
    /// 从文件加载配置
    pub async fn from_file<P: Into<PathBuf>>(path: P) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
        let content = tokio::fs::read_to_string(path.into()).await?;
        let config: ScanConfig = serde_yaml::from_str(&content)?;
        Ok(config)
    }

    /// 保存配置到文件
    pub async fn save_to_file<P: Into<PathBuf>>(&self, path: P) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let content = serde_yaml::to_string(self)?;
        tokio::fs::write(path.into(), content).await?;
        Ok(())
    }

    /// 获取开发环境配置
    pub fn development() -> Self {
        let mut config = Self::default();
        config.engine.debug = true;
        config.processor.worker_count = 2;
        config.storage.storage_type = StorageType::Memory;
        config.alert.enabled = true;
        config
    }

    /// 获取生产环境配置
    pub fn production() -> Self {
        let mut config = Self::default();
        config.engine.debug = false;
        config.processor.worker_count = num_cpus::get();
        config.storage.storage_type = StorageType::File;
        config.storage.file_storage.path = PathBuf::from("./data/scan_results");
        config.alert.enabled = true;
        config
    }
}

/// 引擎配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EngineConfig {
    /// 引擎名称
    pub name: String,
    /// 版本
    pub version: String,
    /// 调试模式
    pub debug: bool,
    /// 最大并发事件数
    pub max_concurrent_events: usize,
    /// 事件缓冲区大小
    pub event_buffer_size: usize,
    /// 优雅关闭超时时间 (秒)
    pub graceful_shutdown_timeout_seconds: u64,
}

impl Default for EngineConfig {
    fn default() -> Self {
        Self {
            name: "Good-MITM Passive Scan Engine".to_string(),
            version: env!("CARGO_PKG_VERSION").to_string(),
            debug: false,
            max_concurrent_events: 1000,
            event_buffer_size: 10000,
            graceful_shutdown_timeout_seconds: 30,
        }
    }
}

/// 存储配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StorageConfig {
    /// 存储类型
    pub storage_type: StorageType,
    /// 内存存储配置
    pub memory_storage: MemoryStorageConfig,
    /// 文件存储配置
    pub file_storage: FileStorageConfig,
    /// 数据库存储配置
    #[cfg(feature = "database")]
    pub database_storage: DatabaseStorageConfig,
}

impl Default for StorageConfig {
    fn default() -> Self {
        Self {
            storage_type: StorageType::Memory,
            memory_storage: MemoryStorageConfig::default(),
            file_storage: FileStorageConfig::default(),
            #[cfg(feature = "database")]
            database_storage: DatabaseStorageConfig::default(),
        }
    }
}

/// 存储类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum StorageType {
    Memory,
    File,
    #[cfg(feature = "database")]
    Database,
}

/// 内存存储配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryStorageConfig {
    /// 最大条目数
    pub max_entries: usize,
}

impl Default for MemoryStorageConfig {
    fn default() -> Self {
        Self {
            max_entries: 10_000,
        }
    }
}

/// 文件存储配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileStorageConfig {
    /// 存储目录
    pub path: PathBuf,
    /// 最大文件大小 (字节)
    pub max_file_size: usize,
    /// 自动清理过期数据
    pub auto_cleanup: bool,
    /// 数据保留天数
    pub retention_days: u32,
}

impl Default for FileStorageConfig {
    fn default() -> Self {
        Self {
            path: PathBuf::from("./scan_results"),
            max_file_size: 10 * 1024 * 1024, // 10MB
            auto_cleanup: true,
            retention_days: 30,
        }
    }
}

/// 数据库存储配置
#[cfg(feature = "database")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseStorageConfig {
    /// 数据库连接字符串
    pub connection_string: String,
    /// 连接池大小
    pub pool_size: u32,
    /// 自动迁移
    pub auto_migrate: bool,
}

#[cfg(feature = "database")]
impl Default for DatabaseStorageConfig {
    fn default() -> Self {
        Self {
            connection_string: "sqlite:scan_results.db".to_string(),
            pool_size: 10,
            auto_migrate: true,
        }
    }
}

/// 规则配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RulesConfig {
    /// 规则目录
    pub rules_directory: PathBuf,
    /// 自动加载规则
    pub auto_load: bool,
    /// 规则重载间隔 (秒)
    pub reload_interval_seconds: u64,
    /// 启用的规则类型
    pub enabled_rule_types: Vec<String>,
    /// 自定义规则文件
    pub custom_rule_files: Vec<PathBuf>,
}

impl Default for RulesConfig {
    fn default() -> Self {
        Self {
            rules_directory: PathBuf::from("./rules/scan"),
            auto_load: true,
            reload_interval_seconds: 300, // 5分钟
            enabled_rule_types: vec![
                "regex".to_string(),
                "nuclei".to_string(),
                "fingerprint".to_string(),
            ],
            custom_rule_files: Vec::new(),
        }
    }
}

/// 指纹识别配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FingerprintConfig {
    /// 是否启用指纹识别
    pub enabled: bool,
    /// 指纹数据库路径
    pub database_path: PathBuf,
    /// 指纹更新间隔 (小时)
    pub update_interval_hours: u64,
    /// 自定义指纹文件
    pub custom_fingerprint_files: Vec<PathBuf>,
}

impl Default for FingerprintConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            database_path: PathBuf::from("./fingerprints"),
            update_interval_hours: 24,
            custom_fingerprint_files: Vec::new(),
        }
    }
}

/// 性能配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceConfig {
    /// CPU使用限制 (百分比)
    pub cpu_limit_percent: Option<u8>,
    /// 内存使用限制 (MB)
    pub memory_limit_mb: Option<usize>,
    /// GC策略
    pub gc_strategy: GcStrategy,
    /// 压缩配置
    pub compression: CompressionConfig,
}

impl Default for PerformanceConfig {
    fn default() -> Self {
        Self {
            cpu_limit_percent: Some(80),
            memory_limit_mb: Some(1024),
            gc_strategy: GcStrategy::default(),
            compression: CompressionConfig::default(),
        }
    }
}

/// GC策略
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GcStrategy {
    /// 策略类型
    pub strategy: GcStrategyType,
    /// 执行间隔 (秒)
    pub interval_seconds: u64,
    /// 触发阈值
    pub threshold: f64,
}

impl Default for GcStrategy {
    fn default() -> Self {
        Self {
            strategy: GcStrategyType::Adaptive,
            interval_seconds: 60,
            threshold: 0.8,
        }
    }
}

/// GC策略类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum GcStrategyType {
    /// 固定间隔
    Periodic,
    /// 自适应
    Adaptive,
    /// 基于内存压力
    MemoryPressure,
    /// 禁用GC
    Disabled,
}

/// 压缩配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CompressionConfig {
    /// 是否启用压缩
    pub enabled: bool,
    /// 压缩算法
    pub algorithm: CompressionAlgorithm,
    /// 压缩级别
    pub level: u8,
    /// 最小压缩大小 (字节)
    pub min_size_bytes: usize,
}

impl Default for CompressionConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            algorithm: CompressionAlgorithm::Lz4,
            level: 4,
            min_size_bytes: 1024,
        }
    }
}

/// 压缩算法
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CompressionAlgorithm {
    Gzip,
    Lz4,
    Zstd,
}

/// 监控配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringConfig {
    /// 是否启用监控
    pub enabled: bool,
    /// 指标收集间隔 (秒)
    pub metrics_interval_seconds: u64,
    /// Prometheus配置
    pub prometheus: PrometheusConfig,
    /// 健康检查配置
    pub health_check: HealthCheckConfig,
}

impl Default for MonitoringConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            metrics_interval_seconds: 30,
            prometheus: PrometheusConfig::default(),
            health_check: HealthCheckConfig::default(),
        }
    }
}

/// Prometheus配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrometheusConfig {
    /// 是否启用
    pub enabled: bool,
    /// 监听地址
    pub bind_address: String,
    /// 指标路径
    pub metrics_path: String,
}

impl Default for PrometheusConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            bind_address: "127.0.0.1:9090".to_string(),
            metrics_path: "/metrics".to_string(),
        }
    }
}

/// 健康检查配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckConfig {
    /// 是否启用
    pub enabled: bool,
    /// 监听地址
    pub bind_address: String,
    /// 检查路径
    pub health_path: String,
}

impl Default for HealthCheckConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            bind_address: "127.0.0.1:8080".to_string(),
            health_path: "/health".to_string(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_config() {
        let config = ScanConfig::default();

        assert_eq!(config.engine.name, "Good-MITM Passive Scan Engine");
        assert!(config.dedup.max_entries > 0);
        assert!(config.processor.worker_count > 0);
        assert!(config.alert.enabled);
        assert_eq!(config.storage.storage_type, StorageType::Memory);
    }

    #[test]
    fn test_development_config() {
        let config = ScanConfig::development();

        assert!(config.engine.debug);
        assert_eq!(config.processor.worker_count, 2);
        assert_eq!(config.storage.storage_type, StorageType::Memory);
    }

    #[test]
    fn test_production_config() {
        let config = ScanConfig::production();

        assert!(!config.engine.debug);
        assert!(config.processor.worker_count >= 2);
        assert_eq!(config.storage.storage_type, StorageType::File);
    }
}